/** * Create by mzq * Description: 报告单 * Date: 2025/2/12 09:09 * Update:
2025/2/12 09:09 */
<template>
  <view>
    <MyDiaLog
      :visible="true"
      :titleName="'生成报告'"
      :width="800"
      @close="handleClose">
      <template>
        <!-- 添加一个外层容器来控制滚动 -->
        <scroll-view scroll-y="true" class="scroll-container">
          <sp-html2pdf-render
            domId="render-dom"
            ref="renderRef"
            pdfFileName="报告"
            @beforeSavePDF="beforeSavePDF"
            @successSavePDF="successSavePDF"
            @renderOver="renderOver"></sp-html2pdf-render>
          <view class="report-content render-content" id="render-dom">
            <div class="report-header">监测报告单</div>
            <!-- 第一行信息 -->
            <view class="info-line">
              <view class="info-group">
                <text class="label">住院号：</text>
                <text class="value"
                  >{{ (normalizedReportData && normalizedReportData.admissionNumber) || '--' }}
                </text>
              </view>
              <view class="info-group">
                <text class="label">姓名：</text>
                <text class="value"
                  >{{ (normalizedReportData && normalizedReportData.name) || '--' }}
                </text>
              </view>
              <view class="info-group">
                <text class="label">性别：</text>
                <text class="value"
                  >{{ (normalizedReportData && normalizedReportData.sex) || '--' }}
                </text>
              </view>
              <view class="info-group">
                <text class="label">年龄：</text>
                <text class="value"
                  >{{ (normalizedReportData && normalizedReportData.age) || '--' }}
                </text>
              </view>
              <view class="info-group">
                <text class="label">住院科室：</text>
                <text class="value"
                  >{{ (normalizedReportData && normalizedReportData.Department) || '--' }}
                </text>
              </view>
            </view>

            <!-- 第二行信息 -->
            <view class="info-line">
              <view class="info-group">
                <text class="label">影像诊断：</text>
                <text class="value"
                  >{{ (normalizedReportData && normalizedReportData.diagnosis) || '--' }}
                </text>
              </view>
              <view class="info-group">
                <text class="label">损伤部位：</text>
                <text class="value">大脑 </text>
              </view>
            </view>

            <!-- 分割线 -->
            <view class="divider"></view>

            <div>总体趋势</div>
            <!-- 修改为两个独立的图表区域 -->
            <div class="chart-section">
              <div class="chart-legend">
                <span class="legend-text">左脑稳定系数</span>
                <span class="color-indicator left"></span>
              </div>
              <view class="chart-container">
                <l-echart
                  ref="leftChartRef"
                  @finished="initLeftChart"></l-echart>
              </view>
            </div>

            <div class="chart-section">
              <div class="chart-legend">
                <span class="legend-text">右脑稳定系数</span>
                <span class="color-indicator right"></span>
              </div>
              <view class="chart-container">
                <l-echart
                  ref="rightChartRef"
                  @finished="initRightChart"></l-echart>
              </view>
            </div>

            <!-- 在右脑稳定系数后添加全脑稳定系数 -->
            <div class="chart-section">
              <div class="chart-legend">
                <span class="legend-text">全脑稳定系数</span>
                <span class="color-indicator all"></span>
              </div>
              <view class="chart-container">
                <l-echart ref="allChartRef" @finished="initAllChart"></l-echart>
              </view>
            </div>

            <!-- 添加颅内压稳定系数 -->
            <div class="chart-section">
              <div class="chart-legend">
                <span class="legend-text">颅内压稳定系数</span>
                <span class="color-indicator icp"></span>
              </div>
              <view class="chart-container">
                <l-echart ref="icpChartRef" @finished="initIcpChart"></l-echart>
              </view>
            </div>

            <div>监测结论:</div>
            <div class="conclusion-container">
              <view class="conclusion-box">
                <textarea
                  v-model="localMonitoringConclusion"
                  placeholder=""
                  class="conclusion-textarea"
                  @blur="handleConclusionChange"></textarea>
              </view>
            </div>

            <!-- 分割线 -->
            <view class="divider"></view>

            <!-- 完整版签名区域 -->
            <div class="report-footer">
              <div class="footer-item">
                报告生成时间: {{ formattedCreateTime }}
              </div>
              <div class="footer-item signature-container">
                <span class="signature-label">医师签字:</span>
                <template v-if="!reportData || !reportData.signatureImg">
                  <fui-autograph
                    id="myCanvas"
                    width="250"
                    height="150"
                    ref="autograph"
                    @ready="ready"
                    class="signature-pad"></fui-autograph>
                </template>
                <template v-else>
                  <image
                    :src="base64Image || reportData.signatureImg"
                    mode="aspectFit"
                    style="width: 250px; height: 150px;"
                  />
                </template>
              </div>
            </div>

            <!-- 添加底部按钮组 -->
            <div class="button-group" v-show="!simplifiedMode">
              <div>
                <button class="btn btn-default" @click="handleReset">
                  重置
                </button>
              </div>
              <div>
                <button class="btn btn-default" @click="handleSave">
                  保存
                </button>
              </div>
              <div>
                <button class="btn btn-primary" @click="handlePrint">
                  打印
                </button>
              </div>
            </div>
          </view>
        </scroll-view>
      </template>
    </MyDiaLog>
  </view>
</template>

<script>
import { mapState } from 'vuex'
import MyDiaLog from '@/components/MyDiaLog/MyDiaLog.vue'
import * as echarts from '@/uni_modules/lime-echart/static/echarts.min'
import FuiAutograph from '@/components/firstui/fui-autograph/fui-autograph.vue'
import { readJsonFromFile, updateJsonById } from '@/utils/fileUtil'
import SpHtml2pdfRender from '@/uni_modules/sp-html2pdf-render/components/sp-html2pdf-render/sp-html2pdf-render.vue'
import { getAbsolutePath } from '@/utils'

// 添加 requestAnimationFrame polyfill
const requestAnimationFramePolyfill = (callback) => {
  return setTimeout(callback, 16); // 约等于 60fps
};

// 添加 cancelAnimationFrame polyfill
const cancelAnimationFramePolyfill = (id) => {
  clearTimeout(id);
};

// 使用 polyfill 或原生方法
const raf = typeof requestAnimationFrame !== 'undefined' ? requestAnimationFrame : requestAnimationFramePolyfill;
const caf = typeof cancelAnimationFrame !== 'undefined' ? cancelAnimationFrame : cancelAnimationFramePolyfill;

// 改进的数据采样函数 - 使用LTTB算法（Largest-Triangle-Three-Buckets）
function lttbSample(data, threshold) {
  if (!data || !Array.isArray(data) || data.length <= threshold) {
    return data;
  }
  
  // 快速路径：如果数据量极大，先进行粗略采样
  if (data.length > 50000) {
    const preStep = Math.ceil(data.length / 20000);
    const presampled = [];
    for (let i = 0; i < data.length; i += preStep) {
      presampled.push(data[i]);
    }
    data = presampled;
  }
  
  const sampled = [];
  // 始终包含第一个点
  sampled.push(data[0]);
  
  const bucketSize = (data.length - 2) / (threshold - 2);
  let a = 0; // 上一个被选中的点的索引
  
  for (let i = 0; i < threshold - 2; i++) {
    const nextA = Math.floor((i + 1) * bucketSize) + 1;
    const avgX = (nextA + a) / 2;
    
    // 计算当前桶中的点到上一个选中点和平均点连线的距离
    let maxArea = -1;
    let maxAreaIndex = a + 1;
    
    for (let j = a + 1; j < nextA; j++) {
      // 计算三角形面积
      const area = Math.abs(
        (a - avgX) * (data[j] - data[a]) - 
        (a - j) * (avgX - data[a])
      );
      
      if (area > maxArea) {
        maxArea = area;
        maxAreaIndex = j;
      }
    }
    
    sampled.push(data[maxAreaIndex]);
    a = nextA;
  }
  
  // 始终包含最后一个点
  sampled.push(data[data.length - 1]);
  
  return sampled;
}

// 添加数据采样函数 - 优化版本
function sampleData(data, maxPoints = 1000) {
  if (!data || !Array.isArray(data) || data.length <= maxPoints) {
    return data;
  }
  
  // 根据数据量大小动态调整采样点数
  let targetPoints = maxPoints;
  if (data.length > 20000) {
    targetPoints = 1500; // 超大数据集使用更多点
  } else if (data.length > 10000) {
    targetPoints = 1200; // 大数据集使用较多点
  }
  
  // 对于超大数据集(>15000)，使用LTTB算法
  if (data.length > 15000) {
    return lttbSample(data, targetPoints);
  }
  
  // 对于大数据集(>5000)，使用更精细的采样策略
  if (data.length > 5000) {
    // 保留关键点：开始、结束、最大值、最小值和一些均匀分布的点
    const result = [];
    
    // 添加开始的几个点
    for (let i = 0; i < Math.min(10, data.length); i++) {
      result.push(data[i]);
    }
    
    // 快速找出最大值和最小值
    let maxVal = -Infinity;
    let minVal = Infinity;
    let maxIndex = 0;
    let minIndex = 0;
    
    // 使用更小的步长进行扫描，确保不会遗漏重要点
    const scanStep = Math.max(1, Math.floor(data.length / 5000));
    for (let i = 0; i < data.length; i += scanStep) {
      if (data[i] > maxVal) {
        maxVal = data[i];
        maxIndex = i;
      }
      if (data[i] < minVal) {
        minVal = data[i];
        minIndex = i;
      }
    }
    
    // 计算采样间隔 - 减少步长，增加采样点
    const step = Math.ceil(data.length / (targetPoints - 20));
    
    // 均匀采样
    for (let i = 10; i < data.length - 10; i += step) {
      result.push(data[i]);
    }
    
    // 确保最大值和最小值被包含
    if (!result.includes(data[maxIndex])) {
      result.push(data[maxIndex]);
    }
    
    if (!result.includes(data[minIndex])) {
      result.push(data[minIndex]);
    }
    
    // 添加结束的几个点
    for (let i = Math.max(0, data.length - 10); i < data.length; i++) {
      result.push(data[i]);
    }
    
    return result;
  }
  
  // 对于中等数据集，使用简单的均匀采样，但保留更多点
  const step = Math.ceil(data.length / targetPoints);
  
  // 采样数据
  const sampledData = [];
  for (let i = 0; i < data.length; i += step) {
    sampledData.push(data[i]);
  }
  
  // 确保包含最后一个点
  if (sampledData[sampledData.length - 1] !== data[data.length - 1]) {
    sampledData.push(data[data.length - 1]);
  }
  
  return sampledData;
}

// 添加异步数据处理函数，支持分块处理和Web Worker
function processDataAsync(data, callback) {
  return new Promise(resolve => {
    // 如果数据量小，直接处理
    if (!data || !Array.isArray(data) || data.length < 1000) {
      const result = sampleData(data);
      if (callback) callback(result);
      resolve(result);
      return;
    }
    
    // 尝试使用Web Worker处理大数据集
    try {
      // 检查是否支持Web Worker
      if (typeof Worker !== 'undefined') {
        // 创建内联Worker
        const workerCode = `
          self.onmessage = function(e) {
            const data = e.data;
            
            // Worker内部的采样函数
            function lttbSample(data, threshold) {
              if (!data || !Array.isArray(data) || data.length <= threshold) {
                return data;
              }
              
              // 快速路径：如果数据量极大，先进行粗略采样
              if (data.length > 50000) {
                const preStep = Math.ceil(data.length / 20000);
                const presampled = [];
                for (let i = 0; i < data.length; i += preStep) {
                  presampled.push(data[i]);
                }
                data = presampled;
              }
              
              const sampled = [];
              // 始终包含第一个点
              sampled.push(data[0]);
              
              const bucketSize = (data.length - 2) / (threshold - 2);
              let a = 0; // 上一个被选中的点的索引
              
              for (let i = 0; i < threshold - 2; i++) {
                const nextA = Math.floor((i + 1) * bucketSize) + 1;
                const avgX = (nextA + a) / 2;
                
                // 计算当前桶中的点到上一个选中点和平均点连线的距离
                let maxArea = -1;
                let maxAreaIndex = a + 1;
                
                for (let j = a + 1; j < nextA; j++) {
                  // 计算三角形面积
                  const area = Math.abs(
                    (a - avgX) * (data[j] - data[a]) - 
                    (a - j) * (avgX - data[a])
                  );
                  
                  if (area > maxArea) {
                    maxArea = area;
                    maxAreaIndex = j;
                  }
                }
                
                sampled.push(data[maxAreaIndex]);
                a = nextA;
              }
              
              // 始终包含最后一个点
              sampled.push(data[data.length - 1]);
              
              return sampled;
            }
            
            // 根据数据量大小动态调整采样点数
            let targetPoints = 1000;
            if (data.length > 20000) {
              targetPoints = 1500; // 超大数据集使用更多点
            } else if (data.length > 10000) {
              targetPoints = 1200; // 大数据集使用较多点
            }
            
            // 根据数据量选择采样方法
            let result;
            if (data.length > 15000) {
              result = lttbSample(data, targetPoints);
            } else if (data.length > 5000) {
              // 保留关键点采样
              result = [];
              
              // 添加开始的几个点
              for (let i = 0; i < Math.min(10, data.length); i++) {
                result.push(data[i]);
              }
              
              // 快速找出最大值和最小值
              let maxVal = -Infinity;
              let minVal = Infinity;
              let maxIndex = 0;
              let minIndex = 0;
              
              const scanStep = Math.max(1, Math.floor(data.length / 5000));
              for (let i = 0; i < data.length; i += scanStep) {
                if (data[i] > maxVal) {
                  maxVal = data[i];
                  maxIndex = i;
                }
                if (data[i] < minVal) {
                  minVal = data[i];
                  minIndex = i;
                }
              }
              
              // 计算采样间隔
              const step = Math.ceil(data.length / (targetPoints - 20));
              
              // 均匀采样
              for (let i = 10; i < data.length - 10; i += step) {
                result.push(data[i]);
              }
              
              // 确保最大值和最小值被包含
              if (!result.includes(data[maxIndex])) {
                result.push(data[maxIndex]);
              }
              
              if (!result.includes(data[minIndex])) {
                result.push(data[minIndex]);
              }
              
              // 添加结束的几个点
              for (let i = Math.max(0, data.length - 10); i < data.length; i++) {
                result.push(data[i]);
              }
            } else {
              // 简单均匀采样
              const step = Math.ceil(data.length / targetPoints);
              
              result = [];
              for (let i = 0; i < data.length; i += step) {
                result.push(data[i]);
              }
              
              // 确保包含最后一个点
              if (result[result.length - 1] !== data[data.length - 1]) {
                result.push(data[data.length - 1]);
              }
            }
            
            self.postMessage(result);
          };
        `;
        
        // 创建Blob URL
        const blob = new Blob([workerCode], { type: 'application/javascript' });
        const workerUrl = URL.createObjectURL(blob);
        
        // 创建Worker
        const worker = new Worker(workerUrl);
        
        // 设置消息处理
        worker.onmessage = function(e) {
          const result = e.data;
          if (callback) callback(result);
          resolve(result);
          
          // 清理资源
          worker.terminate();
          URL.revokeObjectURL(workerUrl);
        };
        
        // 设置错误处理
        worker.onerror = function(error) {
          console.error('Worker错误:', error);
          // 回退到主线程处理
          const fallbackData = simpleFallbackSampling(data);
          if (callback) callback(fallbackData);
          resolve(fallbackData);
          
          // 清理资源
          worker.terminate();
          URL.revokeObjectURL(workerUrl);
        };
        
        // 发送数据到Worker
        worker.postMessage(data);
        return;
      }
    } catch (error) {
      console.error('创建Worker失败:', error);
      // 继续使用主线程处理
    }
    
    // 如果Web Worker不可用或创建失败，回退到主线程处理
    // 使用setTimeout分块处理，避免阻塞UI
    setTimeout(() => {
      try {
        const result = sampleData(data);
        if (callback) callback(result);
        resolve(result);
      } catch (error) {
        console.error('数据处理错误:', error);
        // 出错时返回简化版数据
        const fallbackData = simpleFallbackSampling(data);
        if (callback) callback(fallbackData);
        resolve(fallbackData);
      }
    }, 0);
  });
}

// 简单的备用采样方法，在主方法失败时使用
function simpleFallbackSampling(data) {
  if (!data || !Array.isArray(data)) return [];
  
  const maxPoints = 600; // 增加点数，确保图表显示效果
  if (data.length <= maxPoints) return data;
  
  const result = [];
  const step = Math.ceil(data.length / maxPoints);
  
  for (let i = 0; i < data.length; i += step) {
    result.push(data[i]);
  }
  
  return result;
}

export default {
  name: 'LaboratoryReport',
  components: {
    SpHtml2pdfRender,
    FuiAutograph,
    MyDiaLog,
  },
  props: {
    // 添加 props 接收数据
    reportData: {
      type: Object,
      default: () => null,
    },
    // 添加预处理数据的prop，允许从父组件传入已处理的数据
    preprocessedData: {
      type: Object,
      default: () => null,
    },
  },
  data() {
    return {
      // 左脑稳定系数配置
      leftOption: {
        title: { text: '' },
        tooltip: { show: false },  // 禁用提示框
        grid: {
          top: '5%',
          left: '2%',
          right: '2%',
          bottom: '3%',
          containLabel: true,
          show: true,
          backgroundColor: '#fff',
          borderColor: '#eee',
        },
        xAxis: {
          type: 'category',
          boundaryGap: false,
          data: [],
          splitLine: {
            show: true,
            lineStyle: { color: '#eee', type: 'solid' },
          },
          axisLine: { show: false },
          axisTick: { show: false },
          axisLabel: { show: false },
        },
        yAxis: {
          type: 'value',
          scale: true, // 使用数值缩放
          min: function(value) {
            // 计算数据的最小值，并稍微减小一些，确保线条不会贴着底部
            return value.min - (value.max - value.min) * 0.2;
          },
          max: function(value) {
            // 计算数据的最大值，并稍微增大一些，确保线条不会贴着顶部
            return value.max + (value.max - value.min) * 0.2;
          },
          splitLine: {
            show: true,
            lineStyle: { color: '#eee', type: 'solid' },
          },
          axisLine: { show: false },
          axisTick: { show: false },
          axisLabel: { 
            show: false, // 隐藏y轴标签
          },
        },
        series: [
          {
            name: '左脑稳定系数',
            type: 'line',
            data: [],
            lineStyle: {
              color: '#CFE5C8',
              width: 2,
            },
            itemStyle: { color: '#CFE5C8' },
            symbol: 'none',
            smooth: true,
            silent: true,
            sampling: 'average', // 使用LTTB采样算法减少数据点
            progressive: 500, // 渐进式渲染，每帧渲染500个点
            progressiveThreshold: 1000, // 超过1000个点时启用渐进式渲染
            large: true, // 启用大数据模式
            largeThreshold: 100, // 超过100个点时启用大数据模式
          },
        ],
        animation: false,  // 禁用动画
        hoverLayerThreshold: Infinity,  // 禁用hover层
        renderer: 'canvas', // 使用canvas渲染器，性能更好
        progressive: 500, // 全局渐进式渲染设置
        progressiveThreshold: 1000,
        blendMode: 'source-over', // 使用默认混合模式，性能更好
        useUTC: true, // 使用UTC时间，避免时区转换
        lazyUpdate: true, // 启用延迟更新
        silent: true, // 禁用所有交互
      },
      // 右脑稳定系数配置
      rightOption: {
        title: { text: '' },
        tooltip: { show: false },  // 禁用提示框
        grid: {
          top: '5%',
          left: '2%',
          right: '2%',
          bottom: '3%',
          containLabel: true,
          show: true,
          backgroundColor: '#fff',
          borderColor: '#eee',
        },
        xAxis: {
          type: 'category',
          boundaryGap: false,
          data: [],
          splitLine: {
            show: true,
            lineStyle: { color: '#eee', type: 'solid' },
          },
          axisLine: { show: false },
          axisTick: { show: false },
          axisLabel: { show: false },
        },
        yAxis: {
          type: 'value',
          scale: true, // 使用数值缩放
          min: function(value) {
            // 计算数据的最小值，并稍微减小一些，确保线条不会贴着底部
            return value.min - (value.max - value.min) * 0.2;
          },
          max: function(value) {
            // 计算数据的最大值，并稍微增大一些，确保线条不会贴着顶部
            return value.max + (value.max - value.min) * 0.2;
          },
          splitLine: {
            show: true,
            lineStyle: { color: '#eee', type: 'solid' },
          },
          axisLine: { show: false },
          axisTick: { show: false },
          axisLabel: { 
            show: false, // 隐藏y轴标签
          },
        },
        series: [
          {
            name: '右脑稳定系数',
            type: 'line',
            data: [],
            lineStyle: {
              color: '#F1A368',
              width: 2,
            },
            itemStyle: { color: '#F1A368' },
            smooth: true,
            symbol: 'none',
            silent: true,
            sampling: 'average', // 使用LTTB采样算法减少数据点
            progressive: 500, // 渐进式渲染，每帧渲染500个点
            progressiveThreshold: 1000, // 超过1000个点时启用渐进式渲染
            large: true, // 启用大数据模式
            largeThreshold: 100, // 超过100个点时启用大数据模式
          },
        ],
        animation: false,  // 禁用动画
        hoverLayerThreshold: Infinity,  // 禁用hover层
        renderer: 'canvas', // 使用canvas渲染器，性能更好
        progressive: 500, // 全局渐进式渲染设置
        progressiveThreshold: 1000,
        blendMode: 'source-over', // 使用默认混合模式，性能更好
        useUTC: true, // 使用UTC时间，避免时区转换
        lazyUpdate: true, // 启用延迟更新
        silent: true, // 禁用所有交互
      },
      // 全脑稳定系数配置
      allOption: {
        title: { text: '' },
        tooltip: { show: false },  // 禁用提示框
        grid: {
          top: '5%',
          left: '2%',
          right: '2%',
          bottom: '3%',
          containLabel: true,
          show: true,
          backgroundColor: '#fff',
          borderColor: '#eee',
        },
        xAxis: {
          type: 'category',
          boundaryGap: false,
          data: [],
          splitLine: {
            show: true,
            lineStyle: { color: '#eee', type: 'solid' },
          },
          axisLine: { show: false },
          axisTick: { show: false },
          axisLabel: { show: false },
        },
        yAxis: {
          type: 'value',
          scale: true, // 使用数值缩放
          min: function(value) {
            // 计算数据的最小值，并稍微减小一些，确保线条不会贴着底部
            return value.min - (value.max - value.min) * 0.2;
          },
          max: function(value) {
            // 计算数据的最大值，并稍微增大一些，确保线条不会贴着顶部
            return value.max + (value.max - value.min) * 0.2;
          },
          splitLine: {
            show: true,
            lineStyle: { color: '#eee', type: 'solid' },
          },
          axisLine: { show: false },
          axisTick: { show: false },
          axisLabel: { 
            show: false, // 隐藏y轴标签
          },
        },
        series: [
          {
            name: '全脑稳定系数',
            type: 'line',
            data: [],
            lineStyle: {
              color: '#10A6EA',
              width: 2,
            },
            symbol: 'none',
            itemStyle: { color: '#10A6EA' },
            smooth: true,
            silent: true,
            sampling: 'average', // 使用LTTB采样算法减少数据点
            progressive: 500, // 渐进式渲染，每帧渲染500个点
            progressiveThreshold: 1000, // 超过1000个点时启用渐进式渲染
            large: true, // 启用大数据模式
            largeThreshold: 100, // 超过100个点时启用大数据模式
          },
        ],
        animation: false,  // 禁用动画
        hoverLayerThreshold: Infinity,  // 禁用hover层
        renderer: 'canvas', // 使用canvas渲染器，性能更好
        progressive: 500, // 全局渐进式渲染设置
        progressiveThreshold: 1000,
        blendMode: 'source-over', // 使用默认混合模式，性能更好
        useUTC: true, // 使用UTC时间，避免时区转换
        lazyUpdate: true, // 启用延迟更新
        silent: true, // 禁用所有交互
      },

      // 颅内压稳定系数配置
      icpOption: {
        title: { text: '' },
        tooltip: { show: false },  // 禁用提示框
        grid: {
          top: '5%',
          left: '2%',
          right: '2%',
          bottom: '3%',
          containLabel: true,
          show: true,
          backgroundColor: '#fff',
          borderColor: '#eee',
        },
        xAxis: {
          type: 'category',
          boundaryGap: false,
          data: [],
          splitLine: {
            show: true,
            lineStyle: { color: '#eee', type: 'solid' },
          },
          axisLine: { show: false },
          axisTick: { show: false },
          axisLabel: { show: false },
        },
        yAxis: {
          type: 'value',
          scale: true, // 添加scale属性，使用数值缩放
          min: function(value) {
            // 计算数据的平均值
            const avg = (value.max + value.min) / 2;
            // 计算数据范围
            const range = value.max - value.min;
            // 使用固定的放大系数，确保上下有足够空间
            return avg - range * 1.5;
          },
          max: function(value) {
            // 计算数据的平均值
            const avg = (value.max + value.min) / 2;
            // 计算数据范围
            const range = value.max - value.min;
            // 使用固定的放大系数，确保上下有足够空间
            return avg + range * 1.5;
          },
          splitLine: {
            show: true,
            lineStyle: { color: '#eee', type: 'solid' },
          },
          axisLine: { show: false },
          axisTick: { show: false },
          axisLabel: { 
            show: false, // 隐藏y轴标签
          },
        },
        series: [
          {
            name: '颅内压稳定系数',
            type: 'line',
            data: [],
            lineStyle: {
              color: '#FFD700',
              width: 2, // 与全脑图表保持一致的线条宽度
              shadowColor: 'rgba(255, 215, 0, 0.3)', // 减轻阴影效果
              shadowBlur: 3,
              shadowOffsetY: 2
            },
            symbol: 'none',
            itemStyle: { color: '#FFD700' },
            smooth: true,
            silent: true,
            sampling: 'average', // 使用LTTB采样算法减少数据点
            progressive: 500, // 渐进式渲染，每帧渲染500个点
            progressiveThreshold: 1000, // 超过1000个点时启用渐进式渲染
            large: true, // 启用大数据模式
            largeThreshold: 100, // 超过100个点时启用大数据模式
          },
        ],
        animation: false,  // 禁用动画
        hoverLayerThreshold: Infinity,  // 禁用hover层
        renderer: 'canvas', // 使用canvas渲染器，性能更好
        progressive: 500, // 全局渐进式渲染设置
        progressiveThreshold: 1000,
        blendMode: 'source-over', // 使用默认混合模式，性能更好
        useUTC: true, // 使用UTC时间，避免时区转换
        lazyUpdate: true, // 启用延迟更新
        silent: true, // 禁用所有交互
      },

      //   签字
      canvasId: '',
      // 签名保存的图片
      src: '', // 临时存储签名图片路径
      tempDestroyAutograph: false, // 控制签名组件的显示/隐藏
      tempSignatureImage: '', // 临时存储签名的 base64 图片数据
      simplifiedMode: false, // 控制是否显示简化版布局（用于打印）
      base64Image: '', // 存储转换后的 base64 图片数据
      localMonitoringConclusion: '', // 添加本地监测结论变量
      
      // 添加图表初始化状态跟踪
      chartsInitialized: false,
      // 添加处理后的数据缓存
      processedData: {
        left: null,
        right: null,
        all: null,
        icp: null
      }
    }
  },
  methods: {
    // 预处理数据，在组件创建时进行
    async preprocessData() {
      // 如果已经有预处理的数据，直接使用
      if (this.preprocessedData) {
        console.log('使用预处理的数据');
        this.processedData = this.preprocessedData;
        return;
      }
      
      if (!this.reportData) {
        console.error('没有报告数据，无法预处理');
        return;
      }
      
      // 确保reportData是对象而不是数组
      const reportData = Array.isArray(this.reportData) ? this.reportData[0] : this.reportData;
      
      console.log('开始预处理数据:', {
        hasLeftBrain: !!reportData.leftBrainImpedance,
        hasRightBrain: !!reportData.rightBrainImpedance,
        hasAllBrain: !!reportData.stabilityWholeBrain,
        hasIcp: !!reportData.allBrainImpedance
      });
      
      // 显示加载提示
      uni.showLoading({
        title: '处理数据中...',
        mask: true
      });
      
      try {
        // 使用Promise.all并行处理所有数据
        const promises = [];
        
        // 预处理左脑数据
        if (reportData.leftBrainImpedance && reportData.leftBrainImpedance.length > 0) {
          console.log('预处理左脑数据，长度:', reportData.leftBrainImpedance.length);
          promises.push(
            processDataAsync(reportData.leftBrainImpedance, result => {
              this.processedData.left = result;
              console.log('左脑数据处理完成，结果长度:', result.length);
            })
          );
        } else {
          console.warn('没有左脑数据可处理');
          this.processedData.left = [];
        }
        
        // 预处理右脑数据
        if (reportData.rightBrainImpedance && reportData.rightBrainImpedance.length > 0) {
          console.log('预处理右脑数据，长度:', reportData.rightBrainImpedance.length);
          promises.push(
            processDataAsync(reportData.rightBrainImpedance, result => {
              this.processedData.right = result;
              console.log('右脑数据处理完成，结果长度:', result.length);
            })
          );
        } else {
          console.warn('没有右脑数据可处理');
          this.processedData.right = [];
        }
        
        // 预处理全脑数据
        if (reportData.stabilityWholeBrain && reportData.stabilityWholeBrain.length > 0) {
          console.log('预处理全脑数据，长度:', reportData.stabilityWholeBrain.length);
          promises.push(
            processDataAsync(reportData.stabilityWholeBrain, result => {
              this.processedData.all = result;
              console.log('全脑数据处理完成，结果长度:', result.length);
            })
          );
        } else {
          console.warn('没有全脑数据可处理');
          this.processedData.all = [];
        }
        
        // 预处理颅内压数据
        if (reportData.allBrainImpedance && reportData.allBrainImpedance.length > 0) {
          console.log('预处理颅内压数据，长度:', reportData.allBrainImpedance.length);
          
          // 检查数据长度是否与其他数据一致
          const expectedLength = Math.max(
            reportData.leftBrainImpedance?.length || 0,
            reportData.rightBrainImpedance?.length || 0,
            reportData.stabilityWholeBrain?.length || 0
          );
          
          // 如果颅内压数据长度不一致，补齐数据
          let icpData = [...reportData.allBrainImpedance];
          
          promises.push(
            processDataAsync(icpData, result => {
              this.processedData.icp = result;
              console.log('颅内压数据处理完成，结果长度:', result.length);
            })
          );
        } else {
          console.warn('没有颅内压数据可处理');
          this.processedData.icp = [];
        }
        
        // 等待所有数据处理完成
        if (promises.length > 0) {
          console.log('等待所有数据处理完成...');
          await Promise.all(promises);
          console.log('所有数据处理完成');
        } else {
          console.warn('没有数据需要处理');
        }
      } catch (error) {
        console.error('数据预处理失败:', error);
        // 出错时使用简单处理
        this.fallbackDataProcessing();
      } finally {
        // 隐藏加载提示
        uni.hideLoading();
      }
    },
    
    // 备用数据处理方法
    fallbackDataProcessing() {
      // 确保reportData是对象而不是数组
      const reportData = Array.isArray(this.reportData) ? this.reportData[0] : this.reportData;
      
      if (reportData.leftBrainImpedance) {
        this.processedData.left = simpleFallbackSampling(reportData.leftBrainImpedance);
      }
      
      if (reportData.rightBrainImpedance) {
        this.processedData.right = simpleFallbackSampling(reportData.rightBrainImpedance);
      }
      
      if (reportData.stabilityWholeBrain) {
        this.processedData.all = simpleFallbackSampling(reportData.stabilityWholeBrain);
      }
      
      if (reportData.allBrainImpedance) {
        this.processedData.icp = simpleFallbackSampling(reportData.allBrainImpedance);
      }
    },
    
    // 分批初始化图表
    initChartsSequentially() {
      // 如果已经初始化过，不再重复初始化
      if (this.chartsInitialized) return;
      
      // 标记为已初始化
      this.chartsInitialized = true;
      
      // 显示加载提示
      uni.showLoading({
        title: '加载图表...',
        mask: true
      });
      
      // 并行初始化所有图表，而不是串行
      this.parallelChartInit();
    },
    
    // 并行初始化所有图表
    async parallelChartInit() {
      try {
        // 创建所有图表初始化的Promise
        const promises = [
          this.initLeftChart(),
          this.initRightChart(),
          this.initAllChart(),
          this.initIcpChart()
        ];
        
        // 并行执行所有初始化
        await Promise.all(promises);
        
        // 所有图表初始化完成
        uni.hideLoading();
      } catch (error) {
        console.error('图表初始化失败:', error);
        uni.hideLoading();
      }
    },
    
    async initLeftChart() {
      console.log("初始化左脑图表");
      try {
        const chart = await this.$refs.leftChartRef.init(echarts);
        
        // 使用预处理的数据
        if (this.processedData.left) {
          const data = this.processedData.left;
          // 判断数据量，如果少于30条，则显示30条x轴数据，否则显示全部
          const xAxisLength = data.length < 30 ? 30 : data.length;
          this.leftOption.xAxis.data = Array.from(
            { length: xAxisLength },
            (_, i) => i + 1
          );
          this.leftOption.series[0].data = data;
        }
        
        // 使用 setTimeout 替代 requestAnimationFrame
        return new Promise(resolve => {
          setTimeout(() => {
            try {
              chart.setOption(this.leftOption, true, true); // 第二个参数为notMerge，第三个参数为lazyUpdate
              resolve();
            } catch (error) {
              console.error("设置左脑图表选项失败:", error);
              resolve(); // 即使失败也继续执行
            }
          }, 16);
        });
      } catch (error) {
        console.error("初始化左脑图表失败:", error);
        return Promise.resolve(); // 即使失败也继续执行
      }
    },
    
    async initRightChart() {
      console.log("初始化右脑图表");
      try {
        const chart = await this.$refs.rightChartRef.init(echarts);
        
        // 使用预处理的数据
        if (this.processedData.right) {
          const data = this.processedData.right;
          // 判断数据量，如果少于30条，则显示30条x轴数据，否则显示全部
          const xAxisLength = data.length < 30 ? 30 : data.length;
          this.rightOption.xAxis.data = Array.from(
            { length: xAxisLength },
            (_, i) => i + 1
          );
          this.rightOption.series[0].data = data;
        }
        
        // 使用 setTimeout 替代 requestAnimationFrame
        return new Promise(resolve => {
          setTimeout(() => {
            try {
              chart.setOption(this.rightOption, true, true);
              resolve();
            } catch (error) {
              console.error("设置右脑图表选项失败:", error);
              resolve(); // 即使失败也继续执行
            }
          }, 16);
        });
      } catch (error) {
        console.error("初始化右脑图表失败:", error);
        return Promise.resolve();
      }
    },
    
    async initAllChart() {
      console.log("初始化全脑图表");
      try {
        const chart = await this.$refs.allChartRef.init(echarts);
        
        // 使用预处理的数据
        if (this.processedData.all) {
          const data = this.processedData.all;
          console.log("全脑稳定系数数据前5个值:", data.slice(0, 5));
          // 判断数据量，如果少于30条，则显示30条x轴数据，否则显示全部
          const xAxisLength = data.length < 30 ? 30 : data.length;
          this.allOption.xAxis.data = Array.from(
            { length: xAxisLength },
            (_, i) => i + 1
          );
          this.allOption.series[0].data = data;
        }
        
        // 使用 setTimeout 替代 requestAnimationFrame
        return new Promise(resolve => {
          setTimeout(() => {
            try {
              chart.setOption(this.allOption, true, true);
              resolve();
            } catch (error) {
              console.error("设置全脑图表选项失败:", error);
              resolve(); // 即使失败也继续执行
            }
          }, 16);
        });
      } catch (error) {
        console.error("初始化全脑图表失败:", error);
        return Promise.resolve();
      }
    },
    
    async initIcpChart() {
      console.log("初始化颅内压图表",this.processedData);
      try {
        const chart = await this.$refs.icpChartRef.init(echarts);
        
        // 使用预处理的数据
        if (this.processedData.icp) {
          const data = this.processedData.icp;
          console.log("颅内压稳定系数数据前5个值:", data.slice(0, 5));
          

            // 判断数据量，如果少于30条，则显示30条x轴数据，否则显示全部
            const xAxisLength = data.length < 30 ? 30 : data.length;
            this.icpOption.xAxis.data = Array.from(
              { length: xAxisLength },
              (_, i) => i + 1
            );
            
            // 直接使用处理后的数据，不进行额外的标准化处理
            this.icpOption.series[0].data = data;
          }

        
        // 使用 setTimeout 替代 requestAnimationFrame
        return new Promise(resolve => {
          setTimeout(() => {
            try {
              chart.setOption(this.icpOption, true, true);
              resolve();
            } catch (error) {
              console.error("设置颅内压图表选项失败:", error);
              resolve(); // 即使失败也继续执行
            }
          }, 16);
        });
      } catch (error) {
        console.error("初始化颅内压图表失败:", error);
        return Promise.resolve();
      }
    },
    
    ready(e) {
      this.canvasId = e.canvasId
    },

    handleClose() {
      this.$emit('close')
    },

    handleReset() {
      // 清空src
      this.src = ''

      // 清空保存的签名
      const patientReportFile = `/sdcard/test/${this.normalizedReportData.id}.json`;
      updateJsonById(
        this.normalizedReportData.id,
        {
          signatureImg: '',
        },
        patientReportFile
      )

      // 通知父组件更新 reportData
      this.$emit('update:reportData', {
        ...this.normalizedReportData,
        signatureImg: '',
      })

      // 重置签名板
      this.$nextTick(() => {
        if (this.$refs.autograph) {
          this.$refs.autograph.redraw()
        }
      })

      // 显示重置成功提示
      uni.showToast({
        title: '重置成功',
        icon: 'success',
        duration: 2000
      })
    },

    handleSave() {
      if (!this.canvasId || this.src) return

      this.$refs.autograph.drawComplete((res) => {
        this.src = res
        console.log('当前的图片', this.src)
        uni.saveFile({
          tempFilePath: res,
          success: (res2) => {
            const savedFilePath = res2.savedFilePath
            console.log('文件已保存至:', savedFilePath)
            
            // 使用患者ID命名的报告文件路径
            const patientReportFile = `/sdcard/test/${this.normalizedReportData.id}.json`;
            
            // 更新 JSON 文件中的签名图片路径
            updateJsonById(
              this.normalizedReportData.id,
              {
                signatureImg: savedFilePath,
              },
              patientReportFile
            )

            // 读取更新后的数据
            let res3 = readJsonFromFile(patientReportFile)
            console.log('当前患者数据', res3)

            // 通知父组件更新表格数据
            this.$emit('updateTable')

            // 显示保存成功提示
            uni.showToast({
              title: '保存成功',
              icon: 'success',
              duration: 2000
            })
          },
        })
      })
    },

    renderOver(e) {
      // e为导出的图片（base64）
      console.log('==== renderOver :', e)
    },
    beforeSavePDF() {
      // 确保签名组件被隐藏
      this.tempDestroyAutograph = true
    },

    // 将本地文件转换为 base64 格式
    async fileToBase64(filePath) {
      return new Promise((resolve, reject) => {
        plus.io.resolveLocalFileSystemURL(
          filePath,
          (entry) => {
            entry.file((file) => {
              const reader = new plus.io.FileReader()
              reader.onload = (e) => {
                resolve(e.target.result)
              }
              reader.onerror = (e) => {
                reject(e)
              }
              reader.readAsDataURL(file)
            })
          },
          reject
        )
      })
    },

    // 处理打印操作
    handlePrint() {
      // 立即显示密码验证弹框，不等待任何异步操作
      uni.showModal({
        title: '安全验证',
        content: '请输入您的登录密码进行验证',
        editable: true,
        placeholderText: '请输入密码',
        success: async (res) => {
        console.log('用户输入密码:', res);
          if (res.confirm) {
            // 获取输入的密码
            const password = res.content;
            
            // 验证密码不能为空
            if (!password) {
              uni.showToast({
                title: '密码不能为空',
                icon: 'none'
              });
              return;
            }            // 从本地存储获取当前登录用户信息（现在登录时已经保存了）
            const userInfo = uni.getStorageSync('userInfo');
            console.log('当前用户信息:', userInfo);
            // 验证密码是否正确
            if (userInfo && userInfo.password === password) {
              // 密码验证成功，继续打印流程
              // 显示加载提示
              uni.showLoading({
                title: '准备打印...',
                mask: true
              });
              
              try {
                await this.executePrint();
              } catch (error) {
                console.error('打印过程出错:', error);
                uni.showToast({
                  title: '打印准备失败',
                  icon: 'none'
                });
              } finally {
                uni.hideLoading();
              }
            } else {
              // 密码验证失败
              uni.showToast({
                title: '密码验证失败',
                icon: 'none'
              });
            }
          }
        }
      });
    },
    
    // 执行打印操作的方法
    async executePrint() {
      // 如果正在签名，先将签名转换为图片
      if (!this.src && !this.reportData.signatureImg && this.$refs.autograph) {
        await new Promise((resolve) => {
          this.$refs.autograph.drawComplete((res) => {
            this.tempSignatureImage = res // 获取 base64 格式的签名图片
            console.log("测试",res)
            resolve()
          })
        })
      } else if (this.reportData.signatureImg) {
        // 如果已有保存的签名图片，转换为 base64
        try {
          this.base64Image = await this.fileToBase64(
            this.reportData.signatureImg
          )
        } catch (error) {
          console.error('转换图片失败:', error)
        }
      }

      // 切换到简化模式（隐藏不需要打印的元素）
      this.simplifiedMode = true

      // 等待 DOM 更新完成
      await this.$nextTick()

      // 执行打印
      this.$refs.renderRef.h2pRenderDom()

      // 5秒后恢复完整模式
      setTimeout(() => {
        this.simplifiedMode = false
        this.base64Image = '' // 清除临时 base64 图片
      }, 5000)
    },

    // PDF 保存成功的回调
    successSavePDF(path) {
      const printPdf = uni.requireNativePlugin('YanYu-PrintPDF')
      console.log('==== successSavePDF :', path)

      // 清理临时数据
      this.tempSignatureImage = ''
      this.tempDestroyAutograph = false

      // 获取文件绝对路径并打印
      getAbsolutePath(path)
        .then((absolutePath) => {
          console.log('文件的绝对路径:', absolutePath)
          printPdf.managerPrint(absolutePath)
        })
        .catch((error) => {
          console.error('获取绝对路径失败:', error)
          this.tempDestroyAutograph = false
        })
    },

    // 添加监测结论变更处理方法
    handleConclusionChange() {
      // 使用患者ID命名的报告文件路径
      const patientReportFile = `/sdcard/test/${this.normalizedReportData.id}.json`;
      
      // 更新 JSON 文件中的监测结论
      updateJsonById(
        this.normalizedReportData.id,
        {
          MonitoringConclusion: this.localMonitoringConclusion,
        },
        patientReportFile
      )

      // 通知父组件更新 reportData
      this.$emit('update:reportData', {
        ...this.normalizedReportData,
        MonitoringConclusion: this.localMonitoringConclusion,
      })
    },
  },
  watch: {
    'reportData': {
      async handler(newVal) {
        const normalizedData = Array.isArray(newVal) ? newVal[0] : newVal;
        if (normalizedData && normalizedData.signatureImg) {
          try {
            this.base64Image = await this.fileToBase64(normalizedData.signatureImg)
          } catch (error) {
            console.error('转换图片失败:', error)
          }
        } else {
          this.base64Image = ''
        }
      },
      immediate: true
    },
    reportData: {
      immediate: true,
      handler(newVal) {
        const normalizedData = Array.isArray(newVal) ? newVal[0] : newVal;
        if (normalizedData && normalizedData.MonitoringConclusion) {
          this.localMonitoringConclusion = normalizedData.MonitoringConclusion
        }
      },
    },
  },  computed: {
    // 映射 Vuex 中的用户信息
    ...mapState(['userInfo']),
    
    formattedCreateTime() {
      if (!this.normalizedReportData || !this.normalizedReportData.createData) return ''
      const date = new Date(this.normalizedReportData.createData)
      const year = date.getFullYear()
      const month = String(date.getMonth() + 1).padStart(2, '0')
      const day = String(date.getDate()).padStart(2, '0')
      const hours = String(date.getHours()).padStart(2, '0')
      const minutes = String(date.getMinutes()).padStart(2, '0')
      return `${year}-${month}-${day} ${hours}:${minutes}`
    },
    
    // 添加计算属性，确保reportData是对象而不是数组
    normalizedReportData() {
      return Array.isArray(this.reportData) ? this.reportData[0] : this.reportData;
    }
  },
  async created() {
    // 显示UI加载提示
    uni.showLoading({
      title: '加载报告...',
      mask: true
    });
    
    // 如果有签名图片，转换为base64
    if (this.normalizedReportData && this.normalizedReportData.signatureImg) {
      try {
        this.base64Image = await this.fileToBase64(this.normalizedReportData.signatureImg)
      } catch (error) {
        console.error('转换图片失败:', error)
      }
    }

    // 预处理数据 - 使用setTimeout延迟执行，让UI先渲染
    setTimeout(async () => {
      await this.preprocessData();
      // 预处理完成后隐藏加载提示
      uni.hideLoading();
    }, 100);
  },
  mounted() {
    // 使用 nextTick 确保 DOM 已更新
    this.$nextTick(() => {
      // 使用 setTimeout 替代 uni.nextTick，确保在 uni-app 环境中正确运行
      setTimeout(() => {
        // 延迟初始化图表，给 UI 渲染一些时间
        setTimeout(() => {
          this.initChartsSequentially();
        }, 200); // 减少延迟时间，加快图表显示
      }, 50);
    });
  }
}
</script>

<style scoped lang="scss">
// 添加滚动容器样式
.scroll-container {
  height: 70vh; // 设置一个合适的高度，可以根据需要调整
  max-height: 800px; // 设置最大高度
}

.report-content {
  padding: 20px 30px;
  background-color: #fff;
  min-height: 100%; // 确保内容少时也能撑满容器

  .report-header {
    text-align: center;
    font-size: 18px;
    font-weight: bold;
    margin-bottom: 25px;
    color: #000;
  }

  .info-line {
    display: flex;
    flex-wrap: wrap;
    margin-bottom: 15px;
    line-height: 1.8;
    position: relative;

    // 第一行样式
    &:first-of-type {
      display: flex;
      justify-content: space-between;

      .info-group {
        flex: 0 0 auto;
        margin-right: 0;
      }
    }

    // 第二行样式
    &:nth-of-type(2) {
      .info-group {
        &:first-child {
          width: 300px;
        }

        &:last-child {
          position: absolute;
          left: 42%;
        }
      }
    }

    .info-group {
      display: flex;
      align-items: center;

      .label {
        color: #000;
        font-size: 14px;
        white-space: nowrap;
      }

      .value {
        color: #000;
        font-size: 14px;
        margin-left: 4px;
      }
    }
  }

  .divider {
    height: 1px;
    background-color: #000;
    margin: 15px 0;
  }

  .chart-section {
    margin-bottom: 15px; // 两个图表区域之间的间距
  }

  .chart-legend {
    display: flex;
    align-items: center;
    margin-bottom: 5px; // 图例和图表之间的间距

    .legend-text {
      font-size: 14px;
      color: #333;
      margin-right: 8px;
    }

    .color-indicator {
      display: inline-block;
      width: 16px;
      height: 8px;

      &.left {
        background-color: #cfe5c8;
      }

      &.right {
        background-color: #f1a368;
      }

      &.all {
        background-color: #10a6ea;
      }

      &.icp {
        background-color: #ffd700;
      }
    }
  }

  .chart-container {
    width: 100%;
    height: 200rpx;
  }

  .conclusion-container {
    margin-top: 10px;

    .conclusion-box {
      width: 100%;
      min-height: 60px;
      padding: 10px;
      border: 1px solid #ddd;
      border-radius: 4px;
      background-color: #f5f7fa;
      color: #333;
      font-size: 14px;
      line-height: 1.5;

      .conclusion-textarea {
        width: 100%;
        min-height: 40px;
        max-height: 60px;
        border: none;
        background: transparent;
        resize: vertical;
        outline: none;
        font-size: 14px;
        line-height: 1.5;
        color: #333;

        &::placeholder {
          color: #999;
        }
      }
    }
  }

  .report-footer {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    padding: 10px 0;

    .footer-item {
      font-size: 14px;
      color: #333;

      &.signature-container {
        display: flex;
        align-items: flex-start;
        gap: 10px;

        .signature-label {
          white-space: nowrap;
        }

        .signature-pad {
          margin-top: -10px;
        }
      }
    }
  }

  .button-group {
    width: 100%;
    text-align: right;
    display: flex;
    justify-content: flex-end;

    div {
      margin-right: 10px;
    }

    .btn {
      min-width: 80px;
      height: 32px;
      border-radius: 4px;
      font-size: 14px;
      cursor: pointer;
      display: flex;
      align-items: center;
      justify-content: center;

      &:first-child {
        margin-left: 0;
      }

      &.btn-default {
        background-color: #fff;
        color: #333;
        border: 1px solid #ddd; // 改为实线边框
        &:hover {
          border-color: #ccc;
          background-color: #f5f5f5;
        }
      }

      &.btn-primary {
        background-color: #4cd964;
        color: #fff;
        border: none;

        &:hover {
          background-color: #4cd964ee;
        }
      }
    }
  }

  .signature-container {
    .signature-image {
      width: 130px;
      height: 80px;
    }
  }
}
</style>
